<template>
  <div class="copyNot c-bg-sgray c-pb40">
    <audio id="voiceAudio" preload="auto" @error="playAudioEnd" @ended="playAudioEnd" class="c-pf c-p-l-100"></audio>
    <audio id="voiceAudioAnswer" preload="auto" @error="playAudioEnd" @ended="playAudioEnd" class="c-pf c-p-l-100"></audio>
    <div class="c-fs20 c-fs30 c-textAlign-c c-ph24 c-bg-white c-pv36 c-lh c-text-ellipsis1">{{homeWorkInfo.name}}</div>
    <div class="c-bg-white c-mt10">
      <div v-if="homeWorkInfo.cover">
        <img class="c-w100 imgCloseBig" :src="$addXossFilter(homeWorkInfo.cover)" alt="" />
      </div>

      <clock-course-detail-com v-if="homeWorkInfo.description && homeWorkInfo.description.length > 0 && (homeWorkInfo.cover != '' || (homeWorkInfo.description.length == 1 ? homeWorkInfo.description[0].content != '' : true))" :status='0' :description='homeWorkInfo.description' @clickShowDesc='clickShowDesc' @clickShowVideo='clickShowVideo'>
      </clock-course-detail-com>
    </div>
    <section class="c-mt20 c-mh24 c-bg-white c-br20 c-ph30">
      <div class="c-hh60 c-aligni-center c-flex-row">
        <i class="iconfont c-fs20">&#xea41;</i>
        <span class="c-fs20 c-pl10">{{testTime}}</span>
      </div>
      <div class="c-flex-row c-aligni-center c-justify-sb">
        <div class="c-fs26 c-pt10 c-pb20" v-if="questionInfo">【跟读题】第{{questionInfo.number}}题</div>
        <div class="c-ww40 c-hh40" @click="playAudio">
          <img v-show="!showLoudspeaker" class="c-ww40 c-hh40 c-brp50" :src="require('@/assets/i/wap/exam/play.png')" alt="">
          <img v-show="showLoudspeaker" class="c-ww40 c-hh40 c-brp50" :src="require('@/assets/i/wap/exam/loudspeaker.gif')" alt="">
        </div>
      </div>
      <div v-if="questionInfo && questionInfo.cover" class="c-pt10 c-br10">
        <img :src="$addXossFilter(questionInfo.cover)" alt="" class="c-w100">
      </div>
      <div class="c-flex-row c-aligni-center c-pt20">
        <div class="c-fs30 c-fw-b c-lh50" v-if="questionInfo">{{questionInfo.content}}</div>
      </div>
      <div class="c-ww56 c-hh28 c-br6 c-bg-f2 c-fs20 c-fc-gray c-flex-row c-flex-center c-mt20" v-if="questionInfo && questionInfo.translate">译文</div>
      <div class="c-pt10 c-fs24 c-fc-gray" v-if="questionInfo && questionInfo.translate">{{questionInfo.translate}}</div>
      <!-- 录音相关 -->
      <div class="c-flex-row c-aligni-center c-justify-sb c-mt40">
        <div class="c-ww80 c-hh80" @click="clickTryListen">
          <i v-show="curScore !== null && isWeiXin" class="iconfont theme-fc c-fs80">{{isPlayTest ? '&#xe8be;' : '&#xe869;'}}</i>
        </div>
        <div @click="clickRecordBtn" class="record-circle theme-bg c-flex-row c-flex-center">
          <span v-show="recordStatus == 'RECORDING'" class="c-fs40 c-fc-white icon iconfont">&#xe8ae;</span>
          <span v-show="recordStatus == 'START'" class="c-fs40 c-fc-white icon iconfont">&#xe81f;</span>
          <span v-show="recordStatus == 'RESTART'" class="c-fs40 c-fc-white icon iconfont">&#xe825;</span>
        </div>
        <div class="c-ww80 c-hh80">
          <div v-if="curScore !== null" class="c-ww70 c-hh70 theme-bg c-fc-white c-fs32 c-flex-row c-flex-center c-brp50">{{Number(curScore).toFixed(0)}}</div>
        </div>
      </div>
      <div class="c-flex-row c-aligni-center c-justify-sb c-fs20 c-fc-gray c-pt20 c-pb40">
        <div class="c-ww80 c-textAlign-c c-fs20 c-fc-gray">{{curScore !== null && isWeiXin ? '试听':''}}</div>
        <div class="c-fs20">
          <span>{{recordStatusMap[recordStatus]}}</span>
          <span class="theme-fc c-pl10" v-show="recordStatus != 'START'">{{recordTime}}s</span>
        </div>
        <div class="c-ww80 c-textAlign-c c-fs20 c-fc-gray">{{curScore === null ? '':'测评分'}}</div>
      </div>
    </section>
    <div v-if="questionInfo && questionInfo.nextNum == 0 && isDisCheat==2" class="c-mh24 c-mt20 c-br20 c-bg-white c-flex-row c-justify-sb c-ph20 c-pv16 c-aligni-center">
      <div class="c-fs20 c-fc-xblack">打卡可见范围</div>
      <div class="c-fs20 c-fc-gray c-flex-row ">
        <div class="c-bd1-mgray c-pv6 c-ph18 c-mr20 c-br24 c-fw600" :class="enableShow==1?'theme-bd1 theme-bg-10 theme-fc':''" @click="enableShowAll">所有人</div>
        <div class="c-bd1-mgray c-pv6 c-ph18 c-br24 c-fw600" :class="enableShow==0?'theme-bd1 theme-bg-10 theme-fc':''" @click="enableShowOne">仅老师</div>
      </div>
    </div>
    <div class="c-mh24 c-mt20 c-hh72 c-flex-row c-br36 c-fs28 c-text-hidden">
      <div v-show="curNumber > 1" @click="goBefor" class="c-flex-grow1 c-w0 c-bg-white c-flex-row c-flex-center c-hh72">上一题</div>
      <div @click="goNext" class="c-flex-grow1 c-w0 theme-bg c-fc-white c-flex-row c-flex-center c-hh72">{{questionInfo && questionInfo.nextNum == 0 ? '提交':'下一题'}}</div>
    </div>

    <!-- 视频播放器 -->
    <video-popup :showVideo="showVideo" @clickCloseVideo="clickCloseVideo" :videoSrc="currentVideoObj.videoSrc" :m3u8Url="currentVideoObj.m3u8Url"></video-popup>
  </div>
</template>

<script>
import ClockCourseDetailCom from "@/components/templates/clockIn/clockCourseDetailCom.vue";
import { utilJs, wxUtilJs } from "@/utils/common.js"
import record from "@/utils/recorder.js";
import transWorker from '@/utils/transcode.worker.js'
import { Base64 } from '@/utils/base64js.js'
import parser from 'fast-xml-parser'
import videoPopup from "@/components/templates/common/videoPopup.vue";
//const clientW = document.documentElement.clientWidth > 640 ? 640 : document.documentElement.clientWidth; //屏幕宽度
//const videoH = clientW / 320 * 180; //视频高度
let recordTimeCon; //录音计时控制器
let currentLocalId; //当前录音ID
let isLoading = false;
let isLoadingQue = false;
let curHwId = ""; //当前作业ID
let clockInId = ""; //当前课程ID
let testTimeCon = null;
let testTimeTmp = 0;
let examMainId = ""; //当前考试ID
export default {
  name: "VoiceQue",
  components: {
    ClockCourseDetailCom,
    videoPopup
  },
  props: [],
  beforeRouteLeave(to, from, next) {
    //当有评论弹窗的时候，后退就关闭弹窗,因为后退会把history历史栈后退一个，所以要添加回去
    if (this.showVideo) {
      this.showVideo = false;
      history.pushState(null, null, `${window.location.href.split("#")[0]}#${from.fullPath}`);
    } else {
      next();
    }
  },
  data() {
    return {
      theme: localStorage.getItem("colorName") || "mb5_default",
      testTime: '',
      showDesc: false, //显示课程
      showVideo: false, //显示视频
      homeWorkInfo: {},
      questionInfo: null,
      recordStatus: "START",
      recordStatusMap: {
        'START': '点击话筒 开始录音',
        'RECORDING': '点击结束录音',
        'RESTART': '点击重新开始录音',
      },
      recordTime: 0,
      showLoudspeaker: false,
      curScore: null,
      curNumber: 1,
      isPlayTest: false,
      isReTest: false,
      curSelectDate: '', //当前日历打卡日期
      ttId: '', //营期ID
      tpId: '', //环节ID
      tlId: '', //课时ID
      isWeiXin: true,
      qiniuInfo: {}, //录音完后的音频上传到七牛，这里是七牛的相关信息
      blob: '', //录音之后要上传七牛的音频文件
      audioData: [],
      leftDataList: [],
      rightDataList: [],
      integrityScore: '',
      accuracyScore:"", //准确度
      fluencyScore:"", //流畅度分
      answer: [],
      answeraudio: '',
      recordFlag: true,
      workType:'',
      currentVideoObj: {},
      enableShow:1,
      isDisCheat:0
    };
  },
  created() {
    utilJs.appShare(this);
  },
  activated() {
    setDocumentTitle("发表日记"); // eslint-disable-line
    this.initData();

    if (this.curSelectDate) {
      this.getCalendarHomeWork();
    } else {
      this.getHomeWorkDatail();
    }
    this.getQuestionShow();
    this.getBaseConfig()
    this.isWeiXin = utilJs.isWeiXin();
    clearInterval(recordTimeCon);
    this.recordCheck()
    if (!utilJs.isWeiXin() || this.recordFlag) {
      utilJs.getMethod(global.apiurl + "common/qiniu/uploadToken", res => {
        this.qiniuInfo.qiNiuToken = res;
      });
    }
    this.wechatShare();
  },
  deactivated() {
    this.recordStatus = "RECORDING" && wxUtilJs.stopRecord();
    clearInterval(recordTimeCon)
    clearInterval(testTimeCon);
    this.isPlayTest && this.stopListenAudio();
    if (!this.isWeiXin && record != null) {
      record.recClose();
    }
  },
  methods: {
    enableShowAll() {
      this.enableShow = 1
    },
    enableShowOne() {
      this.enableShow = 0
    },
    getBaseConfig() {
      let postUrl = `${global.apiurl}signCard/getBaseConfig?signColId=${clockInId}`;
      utilJs.getMethod(postUrl, (res) => {
        this.isDisCheat = res.isDisCheat
      });
    },
    //添加训练营进度
    setProgress: function () {
      let data = {
        ttId: this.ttId, //营期ID
        tpId: this.tpId, //环节ID
        tlId: this.tlId, //课时ID
        ratio: 100, //完成进度0-100
      }
      utilJs.postMethod(global.apiurl + 'k12/trainings/progress', data, function (res) { });
    },

    goNext() {
      if (!this.questionInfo.nextNum) {
        //没有下一题了，提交作业
        this.summitAnswer();
        return;
      }
      if (this.recordStatus == 'RECORDING') {
        this.$showCjToast({
          text: "请先结束录音",
          type: "warn",
          time: 1500
        });
        return;
      }
      if (this.curScore === null) {
        this.$showCjToast({
          text: "请先录音",
          type: "warn",
          time: 1500
        });
        return;
      }
      this.isPlayTest && this.stopListenAudio();
      this.curNumber = this.questionInfo.nextNum;
      this.showVideo = false;
      this.recordStatus = "START";
      this.recordTime = 0;
      this.hasRecord = 0;
      this.isQuestionEnd = 0;
      this.showLoudspeaker = false;
      this.isPlayTest = false;
      this.curScore = null;
      this.getQuestionShow();
    },
    goBefor() {
      if (this.curNumber == 1) {
        return;
      }
      if (this.recordStatus == 'RECORDING') {
        this.$showCjToast({
          text: "请先结束录音",
          type: "warn",
          time: 1500
        });
        return;
      }
      this.isPlayTest && this.stopListenAudio();
      this.curNumber = this.questionInfo.beforeNum;
      this.showVideo = false;
      this.recordStatus = "START";
      this.recordTime = 0;
      this.hasRecord = 0;
      this.isQuestionEnd = 0;
      this.showLoudspeaker = false;
      this.isPlayTest = false;
      this.curScore = null;
      this.getQuestionShow();
    },
    summitAnswer() {
      if (!this.blob && !currentLocalId) {
        this.$showCjToast({
          text: "请先录音",
          type: "warn",
          time: 1500
        });
        return;
      }
      if (isLoading) {
        return;
      }
      this.isPlayTest && this.stopListenAudio();
      isLoading = true;
      let postData = {
        retest: this.isReTest ? 1 : 0,
        useTime: this.testTime,
        day: this.curSelectDate,
        enableShow: this.enableShow,
      };
      utilJs.postMethod(`${global.apiurl}signCard/finishAIQuestions/${this.homeWorkInfo.hwId}`, postData, res => {
        isLoading = false;
        if (this.ckFrom == global.ckFrom.camp) {
          localStorage.setItem(`camp${this.tlId}`, 100);
          this.setProgress();
        }
        examMainId = res.examMainId
        this.$routerGo(this, "replace", {
          path: "/homePage/clockIn/voiceResult",
          query: {
            curHwId: curHwId,
            totalNum: this.curNumber,
            examMainId: res.examMainId,
            curDate: this.curSelectDate,
            clockInId: clockInId,
            workType:this.workType,
            ttId: this.ttId, //营期ID
            tpId: this.tpId, //环节ID
            tlId: this.tlId, //课时ID
          }
        });
      }, failRes => {
        isLoading = false;
      })
    },
    //上传语音
    uploadVioce() {
      if (this.isWeiXin) {
        if (!currentLocalId) {
          this.$showCjToast({
            text: "请先录音",
            type: "warn",
            time: 1500
          });
          return;
        }
      } else {
        if (!this.blob) {
          this.$showCjToast({
            text: "请先录音",
            type: "warn",
            time: 1500
          });
          return;
        }
      }
      if (isLoading) {
        return;
      }
      this.$loading.show({
        text: "上传中..."
      });
      isLoading = true;
      if (this.isWeiXin) {
        wxUtilJs.uploadVoice({
          localId: currentLocalId
        }).then(serverId => {
          this.saveVoiceAnswer(serverId);
        }).catch(res => {
          this.$loading.hide();
          isLoading = false;
          this.$showCjToast({
            text: "上传失败，请重试",
            type: "warn",
            time: 1500
          });
        });
      } else {
        record.uploadAudioFile(this.blob, this.qiniuInfo, sres => {
          this.saveVoiceAnswer(sres);
        }, () => {
          this.$loading.hide();
          isLoading = false;
        });
      }
    },
    //保存题目
    saveVoiceAnswer(serverId, falg) {
      console.log(this.fluencyScore, 'fluencyScore')
      let postData = {
        day: this.curSelectDate,
        mediaId: serverId,
        questionId: this.questionInfo.questionId,
        recordTime: this.recordTime,
        isFinish: this.questionInfo.nextNum ? 0 : 1,
        useTime: this.questionInfo.nextNum ? 0 : this.testTime,
        retest: this.isReTest ? 1 : 0,
        score: this.curScore, //     分数
        completion: this.integrityScore, //完整度
        accuracyScore: this.accuracyScore, //准确度
        fluencyScore: this.fluencyScore, //流畅度分
        answer: this.answer,
        examMainId: examMainId,
        recordingType: this.recordFlag && falg != 1 ? 1 : 2,
        errorFlag:falg
      };
      utilJs.postMethod(`${global.apiurl}signCard/saveVoiceAnswer`, postData, res => {
        this.$loading.hide();
        isLoading = false;
        if (!this.recordFlag || falg == 1) {
          this.curScore = res.score;
          this.hasRecord = 0
        }
      }, failRes => {
        this.$loading.hide();
        isLoading = false;
      })
    },
    //播放音频
    playAudio() {
      if (this.questionInfo.isDelete == 1) {
        this.$showCjToast({
          text: "该音频已被管理员删除，如有疑问请咨询客服",
          type: "warn",
          time: 1500
        });
        return;
      }
      this.isPlayTest && this.stopListenAudio();
      let audioDom = document.getElementById("voiceAudio");
      if (!audioDom.src || this.showLoudspeaker || this.recordStatus == 'RECORDING') {
        return;
      }
      this.showLoudspeaker = true;
      if (this.isWeiXin) {
        try {
          document.addEventListener("WeixinJSBridgeReady", function () {
            audioDom.play();
          }, false);
          WeixinJSBridge.invoke("getNetworkType", {}, function (e) {// eslint-disable-line
            // 在这里拿到 e.err_msg, 这里面就包含了所有的网络类型
            audioDom.play();
            console.log("WeixinJSBridgeWeixinJSBridgeWeixinJSBridgeWeixinJSBridge");
          });
        } catch (error) {
          // continue regardless of error
        }
      } else {
        audioDom.play();
      }
    },
    playAudioEnd() {
      this.showLoudspeaker = false;
    },
    clickRecordBtn() {
      if (this.recordStatus != "RECORDING") {
        this.clickStartRecord();
      } else {
        this.clickStopRecord();
      }
    },
    // 暂停录音
    recorderStop() {
    // safari下suspend后再次resume录音内容将是空白，设置safari下不做suspend
      if (!(/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgen))) {
        this.audioContext && this.audioContext.suspend()
      }
      this.setStatus('START')
    },
    //检测是否可以录音
    recordCheck() {
      // let $this = this
      this.audioData = []
      // $this.audioData.push(...transWorker.onmessage())
      navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia

    // 创建音频环境
      try {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
        this.audioContext.resume()
        if (!this.audioContext) {
          this.recordFlag = false
          return
        }
      } catch (e) {
        if (!this.audioContext) {
          this.recordFlag = false
          return
        }
      }

    // 获取浏览器录音权限
      if ((navigator.mediaDevices && navigator.mediaDevices.getUserMedia) || navigator.getUserMedia) {
        this.recordFlag = true
      } else {
        this.recordFlag = false
      }
      this.audioContext && this.audioContext.close()
    },
    // 初始化浏览器录音
    recorderInit() {
      // let $this = this
      this.audioData = []
      // $this.audioData.push(...transWorker.onmessage())
      navigator.getUserMedia =
      navigator.getUserMedia ||
      navigator.webkitGetUserMedia ||
      navigator.mozGetUserMedia ||
      navigator.msGetUserMedia

    // 创建音频环境
      try {
        this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
        this.audioContext.resume()
        if (!this.audioContext) {
          this.$showCjToast({
            text: "浏览器不支持webAudioApi相关接口",
            type: "warn",
            time: 1500
          });
          return
        }
      } catch (e) {
        if (!this.audioContext) {
          this.$showCjToast({
            text: "浏览器不支持webAudioApi相关接口",
            type: "warn",
            time: 1500
          });
          return
        }
      }

    // 获取浏览器录音权限
      if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices
        .getUserMedia({
          audio: {sampleRate:48000, autoGainControl:false},
          video: false,
        })
        .then(stream => {
          getMediaSuccess(stream)
        })
        .catch(e => {
          getMediaFail(e)
        })
      } else if (navigator.getUserMedia) {
        navigator.getUserMedia(
          {
            audio: true,
            video: false,
          },
        stream => {
          getMediaSuccess(stream)
        },
        function (e) {
          getMediaFail(e)
        }
      )
      } else {
        this.$showCjToast({
          text: "无法获取浏览器录音功能，请升级浏览器或使用chrome",
          type: "warn",
          time: 1500
        });
        this.audioContext && this.audioContext.close()
        return
      }
    // 获取浏览器录音权限成功的回调
      this.scriptProcessor = []
      this.mediaSource = []
      this.scriptProcessor = []
      let getMediaSuccess = stream => {
        recordTimeCon = setInterval(() => {
          if (this.recordTime < 60) {
            this.recordTime++;
          } else {
            this.clickStopRecord();
          }
        }, 1000);
      // 创建一个用于通过JavaScript直接处理音频
        this.scriptProcessor = this.audioContext.createScriptProcessor(4096, 2, 2)
        this.scriptProcessor.onaudioprocess = e => {
        // 去处理音频数据
          if (this.recordStatus === 'RECORDING') {
            this.audioData = transWorker.onmessage(e.inputBuffer.getChannelData(0))
          }
          let leftChannelData = e.inputBuffer.getChannelData(0)
          let rightChannelData = e.inputBuffer.getChannelData(1)
            // 需要克隆一下
          this.leftDataList.push(leftChannelData.slice(0))
          this.rightDataList.push(rightChannelData.slice(0))
        }
      // 创建一个新的MediaStreamAudioSourceNode 对象，使来自MediaStream的音频可以被播放和操作
        this.mediaSource = this.audioContext.createMediaStreamSource(stream)
      // 连接
        this.mediaSource.connect(this.scriptProcessor)
        this.scriptProcessor.connect(this.audioContext.destination)
        this.connectWebSocket()
      }

      let getMediaFail = (e) => {
        this.$showCjToast({
          text: "请求麦克风失败",
          type: "warn",
          time: 1500
        });
        this.audioContext && this.audioContext.close()
        this.audioContext = undefined
      // 关闭websocket
        if (this.webSocket && this.webSocket.readyState === 1) {
          this.webSocket.close()
        }
      }
    },
     //点击开始录音
    clickStartRecord() {
      if (this.showLoudspeaker) {
        return;
      }
      this.isPlayTest && this.stopListenAudio();
      currentLocalId = '';
      if (this.recordStatus != "START" || this.hasRecord == 1) {
        return;
      }
      this.hasRecord = 1;
      this.wordAnly = '';
      this.isReject = 0;
      this.score = '';
      this.audioData = []
      this.leftDataList = [];
      this.rightDataList = []
      this.recordStatus = "RECORDING";
      this.recordTime = 0;
      clearInterval(recordTimeCon);
      let $this = this;
      if (this.recordFlag) {
        $this.recorderInit()
      } else {
        if (this.isWeiXin) {
          wxUtilJs.startRecord().then(res => {
            recordTimeCon = setInterval(() => {
              if (this.recordTime < 60) {
                this.recordTime++;
              } else {
                this.clickStopRecord();
              }
            }, 1000);
          }, failRes => {
            this.$showCjToast({
              text: "开启录音失败,请确认是否授权录音",
              type: "warn",
              time: 1000
            });
            this.recordStatus = "START";
          });

        //60s后自动停止录音
          wxUtilJs.onVoiceRecordEnd().then(localId => {
            this.recordStatus = "RESTART";
            clearInterval(recordTimeCon);
            currentLocalId = localId;
            this.uploadVioce();
          });
        } else {
          record.recOpen(() => {
            record.recStart();
            recordTimeCon = setInterval(() => {
              if (this.recordTime < 60) {
                this.recordTime++;
              } else {
                this.clickStopRecord();
              }
            }, 1000);
            record.recVoiceRecordEnd(res => {
              this.blob = res;
              this.recordStatus = "RESTART";
              clearInterval(recordTimeCon);
              this.uploadVioce();
            });
          }, () => {
            this.recordStatus = "START";
          }, 'wav');
        }
      }
    },
    mergeArray(list) {
      let length = list.length * list[0].length;
      let data = new Float32Array(length)
      let offset = 0;
      for (let i = 0; i < list.length; i++) {
        data.set(list[i], offset);
        offset += list[i].length;
      }
      return data;
    },
    interleaveLeftAndRight(left, right) {
      let totalLength = left.length + right.length;
      let data = new Float32Array(totalLength);
      for (let i = 0; i < left.length; i++) {
        let k = i * 2;
        data[k] = left[i];
        data[k + 1] = right[i];
      }
      return data;
    },
    writeUTFBytes(view, offset, string) {
      let lng = string.length;
      for (let i = 0; i < lng; i++) {
        view.setUint8(offset + i, string.charCodeAt(i));
      }
    },
    //点击停止录音
    clickStopRecord() {
      if (this.recordStatus != "RECORDING") {
        return;
      }
      clearInterval(recordTimeCon);
      if (this.recordFlag) {
        if (this.recordTime >= 1) {
          this.setStatus("START");
        }
        this.audioContext && this.audioContext.close()
      } else {
        if (this.isWeiXin) {
          wxUtilJs.stopRecord().then(localId => {
            currentLocalId = localId;
            if (this.recordTime >= 1) {
              this.setStatus("START");
              this.uploadVioce();
            }
          });
        } else {
          record.recStop(res => {
            this.blob = res;
            if (this.recordTime >= 1) {
              this.uploadVioce();
            }
          });
        }
      }
      if (this.recordTime < 1) {
        this.$showCjToast({
          text: "录音时间太短",
          type: "warn",
          time: 1000
        });
        this.setStatus("START");
        this.hasRecord = 0;
      }
    },
    createWavFile(audioData) {
      const WAV_HEAD_SIZE = 44;
      let buffer = new ArrayBuffer(audioData.length * 2 + WAV_HEAD_SIZE)
          // 需要用一个view来操控buffer
      let view = new DataView(buffer);
      // 写入wav头部信息
      // RIFF chunk descriptor/identifier
      this.writeUTFBytes(view, 0, 'RIFF');
      // RIFF chunk length
      view.setUint32(4, 44 + audioData.length * 2, true);
      // RIFF type
      this.writeUTFBytes(view, 8, 'WAVE');
      // format chunk identifier
      // FMT sub-chunk
      this.writeUTFBytes(view, 12, 'fmt ');
      // format chunk length
      view.setUint32(16, 16, true);
      // sample format (raw)
      view.setUint16(20, 1, true);
      // stereo (2 channels)
      view.setUint16(22, 2, true);
      // sample rate
      view.setUint32(24, 44100, true);
      // byte rate (sample rate * block align)
      view.setUint32(28, 44100 * 2, true);
      // block align (channel count * bytes per sample)
      view.setUint16(32, 2 * 2, true);
      // bits per sample
      view.setUint16(34, 16, true);
      // data sub-chunk
      // data chunk identifier
      this.writeUTFBytes(view, 36, 'data');
      // data chunk length
      view.setUint32(40, audioData.length * 2, true);
      // 写入PCM数据
      let length = audioData.length;
      let index = 44;
      let volume = 1;
      for (let i = 0; i < length; i++) {
        view.setInt16(index, audioData[i] * (0x7FFF * volume), true);
        index += 2;
      }
      return buffer;
    },
    // 修改录音评测状态
    setStatus(recordStatus) {
      this.recordStatus = recordStatus
    },
    // 连接websocket
    connectWebSocket() {
      utilJs.postMethod(
        global.apiurl + "speech/changeAudio",
        {},
        res => {
          let iseWS
          if ('WebSocket' in window) {
            iseWS = new WebSocket(res.xfUrl)
          }
          this.webSocket = iseWS
          this.setStatus('RECORDING')
          iseWS.onopen = e => {
            this.setStatus('RECORDING')
        // 重新开始录音
            setTimeout(() => {
              this.webSocketSend()
            }, 500)
          }
          iseWS.onmessage = e => {
            this.result(e.data)
          }
          iseWS.onerror = e => {
            this.result(e.data, 1)
            this.recorderStop()
          }
          iseWS.onclose = e => {
            this.recorderStop()
          }
        })
    },
    // 向webSocket发送数据
    webSocketSend() {
      if (this.webSocket.readyState !== 1) {
        return
      }
      let audioData = this.audioData.splice(0, 1280)
      let host = window.location.host;
      var params = {
        common: {
          app_id: host.includes('localhost') || host == "kptest.ckjr001.com" || host == "kptest2.ckjr001.com" ? '5ce4a5a3' : '5d0c50e5',
        },
        business: {
          category: 'read_sentence', // read_syllable/单字朗读，汉语专有 read_word/词语朗读  read_sentence/句子朗读 https://www.xfyun.cn/doc/Ise/IseAPI.html#%E6%8E%A5%E5%8F%A3%E8%B0%83%E7%94%A8%E6%B5%81%E7%A8%8B
          rstcd: 'utf8',
          // group: 'adult',
          sub: 'ise',
          ent: this.speakType == 1 ? 'cn_vip' : 'en_vip',
          tte: 'utf-8',
          cmd: 'ssb',
          auf: 'audio/L16;rate=16000',
          aus: 1,
          aue: 'raw',
          rst: 'entirety',
          ise_unite: "1",
          extra_ability: 'multi_dimension',
          text: '\uFEFF' + this.questionInfo.content
        },
        data: {
          status: 0,
          encoding: 'raw',
          data_type: 1,
          data: this.toBase64(audioData),
        },
      }
      this.webSocket.send(JSON.stringify(params))
      this.handlerInterval = setInterval(() => {
      // websocket未连接
        if (this.webSocket.readyState !== 1) {
          this.audioData = []
          clearInterval(this.handlerInterval)
          return
        }
      // 最后一帧
        if (this.audioData.length === 0) {
          if (this.recordStatus == "START") {
            this.webSocket.send(
            JSON.stringify({
              business: {
                cmd: 'auw',
                aus: 4,
                aue: 'raw'
              },
              data: {
                status: 2,
                encoding: 'raw',
                data_type: 1,
                data: '',
              },
            })
          )
            this.audioData = []
            this.$loading.show({
              text: "计算分数中..."
            });
            clearInterval(this.handlerInterval)
          }
          return false
        }
        audioData = this.audioData.splice(0, 1280)
      // 中间帧
        this.webSocket.send(
        JSON.stringify({
          business: {
            cmd: 'auw',
            aus: 2,
            aue: 'raw'
          },
          data: {
            status: 1,
            encoding: 'raw',
            data_type: 1,
            data: this.toBase64(audioData),
          },
        })
      )
      }, 40)
    },
    // 对处理后的音频数据进行base64编码
    toBase64(buffer) {
      let binary = ''
      let bytes = new Uint8Array(buffer)
      let len = bytes.byteLength
      for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i])
      }
      return window.btoa(binary)
    },
    result(resultData, falg) {
      if (falg == 1) {
        let leftData = this.mergeArray(this.leftDataList)
        let rightData = this.mergeArray(this.rightDataList)
        let audioData = this.interleaveLeftAndRight(leftData, rightData)
        let wavBuffer = this.createWavFile(audioData)
        this.blob = new Blob([new Uint8Array(wavBuffer)], {'type': 'audio/wav'});
        // let blobUrl = URL.createObjectURL(this.blob);
        this.leftDataList = [];
        this.rightDataList = [];
        record.uploadAudioFile(this.blob, this.qiniuInfo, sres => {
          this.recordStatus = "START";
          // https://qnoss.ckjr001.com/1609986768842_mp_voice_v8g4534.wav
          this.answeraudio = sres;
          this.saveVoiceAnswer(sres, falg);
        }, () => {});
    } else {
    // 识别结束
      let jsonData = JSON.parse(resultData)
      if (jsonData.code !== 0) {
        this.isReject = 1
        this.hasRecord = 0;
        this.$loading.hide();
        if (this.isReject == 1) {
          this.$showCjToast({
            text: "请根据题目进行朗读" + jsonData.code,
            type: "warn",
            time: 1500
          });
        }
        this.recordStatus = "START";
        this.webSocket.close()
      } else {
        if (jsonData.data && jsonData.data.data) {
          let data = Base64.decode(jsonData.data.data)
          let grade = parser.parse(data, {
            attributeNamePrefix: '',
            ignoreAttributes: false
          })
          this.hasRecord = 0;
          this.isReject = 0;
          let leftData = this.mergeArray(this.leftDataList)
          let rightData = this.mergeArray(this.rightDataList)
          let audioData = this.interleaveLeftAndRight(leftData, rightData)
          let wavBuffer = this.createWavFile(audioData)
          this.blob = new Blob([new Uint8Array(wavBuffer)], {'type': 'audio/wav'});
          this.leftDataList = [];
          this.rightDataList = [];
          record.uploadAudioFile(this.blob, this.qiniuInfo, sres => {
            this.recordStatus = "START";
            // https://qnoss.ckjr001.com/1609986768842_mp_voice_v8g4534.wav
            let audio = document.getElementById("voiceAudioAnswer");
            audio.src = sres;
            this.answeraudio = sres
            console.log(grade)
            this.setResultText(grade)
            // this.getPoints(sres);
          }, () => {});
        }
        if (jsonData.code === 0 && jsonData.data.status === 2) {
          this.webSocket.close()
        }
      }
      }
    },
    setResultText(grade) {
      let $this = this;
      $this.$loading.hide();
      const readSentence = grade.xml_result.read_sentence.rec_paper
      if ($this.speakType == 1) {
        $this.integrityScore = readSentence.read_sentence.integrity_score
        $this.curScore = readSentence.read_sentence.total_score;
        $this.accuracyScore = readSentence.read_sentence.accuracy_score//准确度
        $this.fluencyScore = readSentence.read_sentence.fluency_score//流畅度分
        // this.answer
      } else {
        $this.curScore = readSentence.read_chapter.total_score
        $this.integrityScore = readSentence.read_chapter.integrity_score
        $this.accuracyScore = readSentence.read_chapter.accuracy_score//准确度
        $this.fluencyScore = readSentence.read_chapter.fluency_score//流畅度分
        if (!Array.isArray(readSentence.read_chapter.sentence)) {
          for (let i = 0; i < readSentence.read_chapter.sentence.word.length; i++) {
            let answercontain = {
              "score": readSentence.read_chapter.sentence.word[i].total_score,
              "time": 0,
              "word": readSentence.read_chapter.sentence.word[i].content
            }
            $this.answer.push(answercontain)
          }
        } else {
          for (let i = 0; i < readSentence.read_chapter.sentence; i++) {
            for (let j = 0; j < readSentence.read_chapter.sentence[i].word.length; j++) {
              if (readSentence.read_chapter.sentence[i].word[j].total_score) {
                let answercontain = {
                  "score": readSentence.read_chapter.sentence[i].word[j].total_score,
                  "time": 0,
                  "word": readSentence.read_chapter.sentence[i].word[j].content
                }
                $this.answer.push(answercontain)
              }
            }
          }
        }
      }
      $this.saveVoiceAnswer($this.answeraudio);
      $this.hasRecord = 0;
      $this.recordStatus = "START";
      $this.answeraudio = ''
    },
    //点击重录
    clickRecordAgain() {
      this.recordStatus = "START";
    },
    //点击试听
    clickTryListen() {
      if (!this.isWeiXin) {
        return;
      }
      if (this.recordFlag) {
        let audio = document.getElementById("voiceAudioAnswer");
        this.isPlayTest = true;
        let audioDom = document.getElementById("voiceAudio");
        audioDom.pause()
        audio.load();
        audio.play();
      } else {
        // if (this.recordStatus != 'START' || this.recordStatus != 'RESTART') {
        //   return;
        // }
        this.isPlayTest = true;
        let audioDom = document.getElementById("voiceAudio");
        audioDom.pause()
        wxUtilJs.playVoice({
          localId: currentLocalId
        });
      }
    },
    stopListenAudio() {
      if (this.isPlayTest) {
        if (this.recordFlag) {
          document.getElementById('voiceAudioAnswer').pause();
        } else {
          wxUtilJs.stopVoice({
            localId: currentLocalId
          });
        }
        this.isPlayTest = false;
      }
    },
    clickShowDesc(isShow) {
      this.showDesc = isShow;
    },

    //点击显示视频
    clickShowVideo(videoSrc, m3u8Url) {
      this.showVideo = true;
      this.currentVideoObj = {videoSrc, m3u8Url}
    },
    //点击关闭视频
    clickCloseVideo() {
      if (this.showVideo) {
        this.showVideo = false;
      }
    },
    // 时间差转成具体时间*天*时*分*秒
    timeTmpToStr(timeTmp) {
      const ONE_DAY_TIMESTAMP = 24 * 60 * 60 * 1000;
      const ONE_HOUR_TIMESTAMP = 60 * 60 * 1000;
      const ONE_MINUTE_TIMESTAMP = 60 * 1000;
      const ONE_SECONDS_TIMESTAMP = 1000;

      //获取天数
      let dayNum = Math.floor(timeTmp / ONE_DAY_TIMESTAMP);
      let hourNum = Math.floor((timeTmp - dayNum * ONE_DAY_TIMESTAMP) / ONE_HOUR_TIMESTAMP);
      let minuteNum = Math.floor((timeTmp - dayNum * ONE_DAY_TIMESTAMP - hourNum * ONE_HOUR_TIMESTAMP) / ONE_MINUTE_TIMESTAMP);
      let secondsNum = Math.floor((timeTmp - dayNum * ONE_DAY_TIMESTAMP - hourNum * ONE_HOUR_TIMESTAMP - minuteNum * ONE_MINUTE_TIMESTAMP) / ONE_SECONDS_TIMESTAMP);
      let returnStr = '';
      if (dayNum > 0) {
        returnStr = `${dayNum}天${hourNum}时${minuteNum}分${secondsNum}秒`;
      } else if (hourNum > 0) {
        returnStr = `${hourNum}时${minuteNum}分${secondsNum}秒`;
      } else if (minuteNum > 0) {
        returnStr = `${minuteNum}分${secondsNum}秒`;
      } else if (secondsNum > 0) {
        returnStr = `${secondsNum}秒`;
      }
      return returnStr;
    },
    //获取作业本信息
    getHomeWorkDatail() {
      utilJs.getMethod(
        global.apiurl + "signCard/homeworkDetail/" + curHwId,
        res => {
          this.homeWorkInfo = res;
          clearInterval(testTimeCon);
          testTimeTmp = 0;
          this.testTime = '';
          testTimeCon = setInterval(() => {
            testTimeTmp++;
            this.testTime = this.timeTmpToStr(testTimeTmp * 1000);
          }, 1000);
          let that = this
          let audio = document.getElementById("voiceAudioAnswer");
            audio.addEventListener('ended', function () {
              that.isPlayTest = false;
          }, false);
          wxUtilJs.onVoicePlayEnd(() => {
            this.isPlayTest = false;
          });
        }
      );
    },

    //获取日历打卡信息
    getCalendarHomeWork() {
      utilJs.getMethod(
        `${global.apiurl}signCard/themeDetail?signColId=${clockInId}&day=${this.curSelectDate}`,
        res => {
          this.homeWorkInfo = {
            hwId: res.headInfo.hwId || 0,
            signColId: clockInId,
            name: res.headInfo.name || '',
            cover: res.headInfo.cover || '',
            description: res.headInfo.description || [],
          };
          clearInterval(testTimeCon);
          testTimeTmp = 0;
          this.testTime = '';
          testTimeCon = setInterval(() => {
            testTimeTmp++;
            this.testTime = this.timeTmpToStr(testTimeTmp * 1000);
          }, 1000);
          let that = this
          let audio = document.getElementById("voiceAudioAnswer");
            audio.addEventListener('ended', function () {
              that.isPlayTest = false;
          }, false);
          wxUtilJs.onVoicePlayEnd(() => {
            this.isPlayTest = false;
          });
        }
      );
    },

    //获取作业信息
    getQuestionShow() {
      if (isLoadingQue) {
        return;
      }
      isLoadingQue = true;
      utilJs.getMethod(`${global.apiurl}signCard/aiQuestionShow/${curHwId}?number=${this.curNumber}&day=${this.curSelectDate}&examMainId=${examMainId}`,
        res => {
          isLoadingQue = false;
          this.questionInfo = res;
          let contant = encodeURIComponent(this.questionInfo.content).replace(/%C2%A0/g, '%20').replace(/%E2%80%A9/g, '').replace(/%E2%80%8B/g, '').replace(/%E2%80%8E/g, '')
          console.log(encodeURIComponent(this.questionInfo.content))
          console.log(contant)
          this.questionInfo.content = decodeURIComponent(contant)
          examMainId = this.questionInfo.examMainId
          this.speakType = this.questionInfo.speakType == 1 ? 1 : 2
          if (!this.isReTest && res.userAnswer.score) {
            this.curScore = res.userAnswer.score;
          }
          document.getElementById('voiceAudio').src = res.contentAudioUrl;
          document.getElementById('voiceAudio').load();
          document.getElementById('voiceAudioAnswer').src = res.userAnswer.mp3Url;
          document.getElementById('voiceAudioAnswer').load();
        }, failRes => {
          isLoadingQue = false;
        }
      );
    },

    initData() {
      isLoading = false;
      isLoadingQue = false;
      currentLocalId = '';
      this.isDisCheat = 0
      curHwId = this.$route.query.curHwId;
      clockInId = this.$route.query.clockInId || '';
      examMainId = this.$route.query.examMainId || -1;
      this.ttId = this.$route.query.ttId || '';
      this.tpId = this.$route.query.tpId || '';
      this.tlId = this.$route.query.tlId || '';
      this.ckFrom = this.$route.query.ckFrom || '';
      this.curSelectDate = this.$route.query.curDate || '';
      this.isReTest = this.$route.query.isReTest || '';
      this.workType = this.$route.query.workType || '';
      this.curNumber = 1;
      this.homeWorkInfo = {};
      this.showDesc = false;
      this.showVideo = false;
      this.recordStatus = "START";
      this.recordTime = 0;
      this.hasRecord = 0;
      this.isQuestionEnd = 0;
      this.showLoudspeaker = false;
      this.isPlayTest = false;
      this.curScore = null;
      this.blob = null;
    },

    //分享
    wechatShare: function () {
      let title = window.localStorage.getItem("companyName");
      let shareImg = window.localStorage.getItem("shareLogo");
      let shareDesc = window.localStorage.getItem("shareDesc");
      let shareUrl = `${window.location.href.split("#")[0]}#${this.$route.path}?refereeId=${localStorage.getItem("userId")}`
      let shareIndexData = {
        shareUrl,
        title,
        shareImg,
        shareDesc,
      };
      let shareData = localStorage.getItem("homeWorkShare") ? JSON.parse(localStorage.getItem("homeWorkShare")) : shareIndexData;
      utilJs.wechatConfig(
        shareData.shareUrl,
        shareData.title,
        shareData.shareImg,
        shareData.shareDesc,
        function () { },
        true
      );
    },
    //手机端分享
    appShare: function () {
      let title = window.localStorage.getItem("companyName");
      let shareImg = window.localStorage.getItem("shareLogo");
      let shareDesc = window.localStorage.getItem("shareDesc");
      let shareUrl = `${window.location.href.split("#")[0]}#${this.$route.path}?refereeId=${localStorage.getItem("userId")}`
      let shareIndexData = {
        shareUrl,
        title,
        shareImg,
        shareDesc,
      };
      let shareData = localStorage.getItem("homeWorkShare") ? JSON.parse(localStorage.getItem("homeWorkShare")) : shareIndexData;
      utilJs.appShareTrue(
        shareData.title,
        shareData.shareImg,
        shareData.shareUrl,
        shareData.shareDesc
      );
    }
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->

<style scoped>
.record-circle {
  /* backface-visibility: hidden;
  -webkit-transform: translate3d(0, 0, 0);
  -moz-transform: translate3d(0, 0, 0);
  -ms-transform: translate3d(0, 0, 0);
  -o-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0); */
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  /* background-color: rgba(249, 180, 73, 1);
  box-shadow: 0px 0px 0px 0.2rem rgba(250, 210, 149, 1); */
}
.record_out {
  backface-visibility: hidden;
  -webkit-transform: translate3d(0, 0, 0);
  -moz-transform: translate3d(0, 0, 0);
  -ms-transform: translate3d(0, 0, 0);
  -o-transform: translate3d(0, 0, 0);
  transform: translate3d(0, 0, 0);
  animation: record_out_zoom 1s infinite linear;
  animation-direction: alternate;
}
@-webkit-keyframes record_out_zoom {
  0% {
    box-shadow: 0px 0px 0px 0.2rem rgba(250, 210, 149, 1);
  }
  100% {
    box-shadow: 0px 0px 0px 0.5rem rgba(250, 210, 149, 1);
  }
}
@keyframes record_out_zoom {
  0% {
    box-shadow: 0px 0px 0px 0.2rem rgba(250, 210, 149, 1);
  }
  100% {
    box-shadow: 0px 0px 0px 0.5rem rgba(250, 210, 149, 1);
  }
}
</style>
